<?php
function start( $c, $a, $m ) {

    $obj = C( $c, null, $m );
    if ( !is_object( $obj ) ) {
        showError( "控制器:{$c} 不存在。<br />" . getRequest( 'REQUEST_URI' ), 'system' );
    }

    if ( !method_exists( $obj, $a ) ) {
        showError( "控制器:{$c} 方法 {$a} 不存在。<br />" . getRequest( 'REQUEST_URI' ), 'system' );
    }

    $obj->$a( $c, $a );
}

/**
 * C  类实例化函数  自动载入类定义文件，实例化并返回对象句柄
 *
 * @param class_name    类名称
 * @param args          类初始化时使用的参数，数组形式
 * @param dir           载入类定义文件的路径
 * @param force_inst    是否强制重新实例化对象
 */
function C( $class_name, $args = null, $dir = null, $force_inst = FALSE ) {
    #检查类名称是否正确，以保证类定义文件载入的安全性
    if ( preg_match( '/[^a-z0-9\-_.]/i', $class_name ) ) showError( $class_name . "类名称错误，请检查。<br />" . getRequest( 'REQUEST_URI' ), 'system' );

    #检查是否该类已经实例化，直接返回已实例对象，避免再次实例化
    if ( TRUE != $force_inst ) if ( isset( $GLOBALS[ "class" ][ $class_name ] ) ) return $GLOBALS[ "class" ][ $class_name ];

    if ( !class_exists( $class_name, false ) ) {
        if ( null != $dir && !file_exists( $dir . $class_name . '.php' ) ) showError( $dir . $class_name . '.php' . "类文件不存在，请检查。<br />" . getRequest( 'REQUEST_URI' ), 'system' );
        require_once $dir . $class_name . '.php';
    }

    #检查类定义是否存在
    if ( class_exists( $class_name, false ) || interface_exists( $class_name, false ) ) {
        $argString = '';
        $comma = '';
        if ( null != $args ) for ( $i = 0; $i < count( $args ); $i++ ) {
            $argString .= $comma . "\$args[$i]";
            $comma = ', ';
        }
        eval( "\$GLOBALS['class'][\$class_name]= new \$class_name($argString);" );
        return $GLOBALS[ "class" ][ $class_name ];
    }

    showError( $class_name . "类定义不存在，请检查。<br />" . getRequest( 'REQUEST_URI' ), 'system' );
}

/**
 * G 获取应用程序请求变量值
 * @param name       获取的变量名称，如果为空，则返回全部的请求变量
 * @param $value     当前获取的变量不存在的时候，返回该值
 */
function G( $name = null, $value = 0 ) {
    if ( $name == null ) {
        return $_REQUEST;
    }
    if ( isset( $_REQUEST[ $name ] ) ) {
        return $_REQUEST[ $name ];
    }
    $_REQUEST[ $name ] = $value;
    return $value;
}

/**
 * mkdirs           递归创建目录
 * @param $dir     目录路径
 */
function mkdirs( $dir ) {
    if ( !is_dir( $dir ) ) {
        mkdirs( dirname( $dir ) );
        umask( 0 );
        mkdir( $dir );
    }
}

/**
 * mkdirs           递遍历删除目录和目录下所有文件
 * @param $dir     目录路径
 * @param $dir     是否删除目录
 */
function del_dir( $dir, $f = true ) {
    if ( !is_dir( $dir ) ) {
        return false;
    }
    $handle = opendir( $dir );
    while ( ( $file = readdir( $handle ) ) !== false ) {
        if ( $file != "." && $file != ".." ) {
            is_dir( "$dir/$file" ) ? del_dir( "$dir/$file" ) : @unlink( "$dir/$file" );
        }
    }
    if ( readdir( $handle ) == false && $f == true) {
        closedir( $handle );
        @rmdir( $dir );
    }
}

/**
 * formatFileSize        格式化文件大小
 * @param $fileSize     原文件大小
 * @param $len          小数点后的位数
 */
function formatFileSize( $fileSize, $len = 2 ) {
    if ( $fileSize >= 1073741824 ) {
        $fileSize = round( $fileSize / 1073741824, $len ) . 'GB';
    } elseif ( $fileSize >= 1048576 ) {
        $fileSize = round( $fileSize / 1048576, $len ) . 'MB';
    } elseif ( $fileSize >= 1024 ) {
        $fileSize = round( $fileSize / 1024, $len ) . 'KB';
    } else {
        $fileSize = $fileSize . '字节';
    }
    return $fileSize;
}

/**
 * formatDate     个性化时间
 * @param $t     要被个性化的时间戳
 */
function formatDate( $t ) {
    if ( !$t ) return '-';
    $t = time() - $t;
    $f = array( '31536000' => '年', '2592000' => '个月', '604800' => '星期', '86400' => '天', '3600' => '小时', '60' => '分钟', '1' => '秒' );
    foreach ( $f as $k => $v ) {
        if ( 0 != $c = floor( $t / (int)$k ) ) {
            $m = floor( $t % $k );
            foreach ( $f as $x => $y ) if ( 0 != $r = floor( $m / (int)$x ) ) return $c . $v . $r . $y . '前';
            return $c . $v . '前';
        }
    }
}

/**
 * substring 字符串截取，支持中文和其他编码
 * @param string $str     需要截取的字符串
 * @param string $start   开始位置
 * @param string $length  截取长度
 * @param string $charset 编码格式
 * @param string $suffix  截断字符串后缀
 */
function substring( $str, $length, $start = 0, $suffix = "...", $charset = "utf-8" ) {
    if ( function_exists( "mb_substr" ) ) {
        return mb_substr( $str, $start, $length, $charset ) . ( mb_strlen( $str ) / 3 > $length ? $suffix : '' );
    } elseif ( function_exists( 'iconv_substr' ) ) {
        return iconv_substr( $str, $start, $length, $charset ) . $suffix;
    }
    $re[ 'utf-8' ] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
    $re[ 'gb2312' ] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
    $re[ 'gbk' ] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
    $re[ 'big5' ] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
    preg_match_all( $re[ $charset ], $str, $match );
    $slice = join( "", array_slice( $match[ 0 ], $start, $length ) );
    return $slice . $suffix;
}

/**
 * md6  数据加密
 * @param str         要加密的字符串
 * @param key         加密密匙
 * @param method      加密方法
 */
function md6( $str = '', $method = 'md5', $key = WEBKEY ) {
    require_once WEBLIB . 'encrypt.php';
    $obj = Encrypt::getInstance();
    $method = "_" . $method;
    $result = $obj->$method( $str, $key );
    return $result;
}

/*
 *  Thumb               生成图片缩略图
 *  @param $src_file    要生成缩略图文件
 *  @param $thumbwidth  要生成缩略图宽度
 *  @param $thumbheight 要生成缩略图高度
 */
function Thumb( $src_file, $thumbwidth = 200, $thumbheight = 200 ) {
    if ( !file_exists( $src_file ) ) return false;

    $tmp = explode( ".", $src_file );
    $thumb_file = $tmp[ 0 ] . '_thumb.' . $tmp[ 1 ];

    $result = getimagesize( WEBROOT . $src_file );
    $imagewidth = $result[ 0 ];
    $imageheight = $result[ 1 ];

    //如果来源图像小于或等于缩略图则拷贝源图像作为缩略图,免去操作
    if ( $imagewidth <= $thumbwidth && $thumbwidth <= $thumbheight ) {
        return $src_file;
    }

    $fileParts = pathinfo( $src_file );
    $type = strtolower( $fileParts[ 'extension' ] ) == 'bmp' ? 'jpg' : strtolower( $fileParts[ 'extension' ] );

    $x_ratio = $thumbwidth / $imagewidth;
    $y_ratio = $thumbheight / $imageheight;
    if ( ( $x_ratio * $imageheight ) < $thumbheight ) {
        $thumb[ 'height' ] = ceil( $x_ratio * $imageheight );
        $thumb[ 'width' ] = $thumbwidth;
    } else {
        $thumb[ 'width' ] = ceil( $y_ratio * $imagewidth );
        $thumb[ 'height' ] = $thumbheight;
    }

    $createfun = 'imagecreatefrom' . ( $type == 'jpg' ? 'jpeg' : $type );
    $outfunc = 'image' . ( $type == 'jpg' ? 'jpeg' : $type );

    $thumb_img = imagecreatetruecolor( $thumb[ 'width' ], $thumb[ 'height' ] );
    $src_img = $createfun( $src_file );

    if ( function_exists( 'imagecopyresampled' ) ) {
        @ImageCopyResampled( $thumb_img, $src_img, 0, 0, 0, 0, $thumb[ 'width' ], $thumb[ 'height' ], $imagewidth, $imageheight );
    } else {
        @ImageCopyResized( $thumb_img, $src_img, 0, 0, 0, 0, $thumb[ 'width' ], $thumb[ 'height' ], $imagewidth, $imageheight );
    }

    //生成缩略图
    $outfunc( $thumb_img, $thumb_file );

    //销毁临时图像
    @ImageDestroy( $src_img );
    @ImageDestroy( $thumb_img );
    return $thumb_file;
}

/**
 * upload           文件上传
 * @param updir    文件保存目录
 * @param $name    表单文件域
 * @param $rename  是否随机文件名
 */
function upload( $updir, $name = 'Filedata', $rename = true ) {

    # 检测hash
    if ( md6( G( 'uphash' ), 'decode' ) != WEBCOOKIE ) {
        return 'hash';
    }

    if ( $_FILES[ $name ][ "error" ] > 0 ) {
        return 'error';
    }

    $tempFile = $_FILES[ $name ][ 'tmp_name' ];

    # 创建上传目录
    $dir = rtrim( date( $updir ), '/' ) . '/';
    $filePath = "content/attachment/" . $dir;
    mkdirs( WEBROOT . $filePath );

    # 上传文件名
    $fileName = $_FILES[ $name ][ 'name' ];

    # 重命名文件
    if ( $rename ) {
        $fileParts = pathinfo( $fileName );
        $fileExt = strtolower( $fileParts[ 'extension' ] ) == 'bmp' ? 'jpg' : strtolower( $fileParts[ 'extension' ] );
        $fileName = strtolower( substr( md5( uniqid() . time() ), 8, 16 ) . '.' . $fileExt );
    }

    # 文件绝对路径
    $filePath .= $fileName;
    return @move_uploaded_file( $tempFile, WEBROOT . $filePath ) ? $filePath : 'error';
}

/**
 * getURL  获取请求信息
 * @param $a    请求参数
 */
function getRequest( $a = 'domain' ) {
    if ( $a == 'domain' ) {
        $http = ( isset( $_SERVER[ 'HTTPS' ] ) && $_SERVER[ 'HTTPS' ] != 'off' ) ? 'https://' : 'http://';
        return "{$http}{$_SERVER['HTTP_HOST']}";
    }
    if ( $a == 'ip' ) {
        $cip = $_SERVER [ "REMOTE_ADDR" ];
        preg_match( "/[\d\.]{7,15}/", $cip, $cips );
        $cip = isset ( $cips [ 0 ] ) ? $cips [ 0 ] : 'unknown';
        unset ( $cips );
        return $cip;
    }
    if ( isset( $_SERVER[ $a ] ) ) {
        return $_SERVER[ $a ];
    }
}

/*
 * filter   请求过滤器
 */
function filter() {
    $getfilter = strtolower( "and,>,<,',(,),like,exec,UNION,SELECT,UPDATE,INSERT,DELETE,CREATE,ALTER,DROP,TRUNCATE" );
    $arr = explode( ",", $getfilter );
    $rq = strtolower( urldecode( getRequest( "QUERY_STRING" ) ) );
    foreach ( $arr as $v ) {
        if ( strpos( $rq, $v ) !== false ) {
            showError( "该请求带有不安全字符! <b style=\"color:red\">{$v}</b><br />" . urldecode( getRequest( 'REQUEST_URI' ) ), 'system' );
            break;
        }
    }
}

/**
 * showError        打印错误信息
 * @param msg      出错信息
 * @param model     出错信息类别
 * @param stop     是否停止程序
 * @param log      写入错误信息到日志文件
 */
function showError( $msg, $model = 'db', $stop = true, $log = true ) {
    $type = $model == null ? "" : ( $model . "\r" );
    ob_get_clean();
    require_once 'debug.php';
    if ( $log ) addlog( $model, $msg );
    if ( TRUE == $stop ) exit;
}

/**
 * addlog        记录系统错误日志
 * @param model     出错信息类别
 * @param msg       错误信息
 */
function addlog( $type = 'db', $msg ) {
    $path = WEBROOT . "content/log/";
    mkdirs( $path );
    $file = $path . md6( $type ) . ".php";
    if ( !file_exists( $file ) ) {
        $msg = "<?php die();?>\n{$msg}";
    }
    $msg .= "==" . time() . "\n";
    $f = @fopen( $file, "a+" );
    @fwrite( $f, $msg );
    @fclose( $f );
    chmod( $file, MODE );
}